package com.zhongkun.datahome.service.export.handler;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.zhongkun.datahome.common.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.Units;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: lifengsheng
 * @Date: 2025/5/13 16:14
 * @Desc
 */
@Slf4j
public class MultiImageCellWriteHandler implements CellWriteHandler {
    /**
     * 单元格的图片最大张数（每列的单元格图片张数不确定，单元格宽度需按照张数最多的长度来设置）
     */
    private final AtomicReference<Integer> MAX_IMAGE_SIZE = new AtomicReference<>(0);

    /**
     * 默认图片宽度（单位像素）：30
     */
    private final static int DEFAULT_IMAGE_WIDTH = 45;

    /**
     * 默认像素转换因子：32
     */
    private final static int DEFAULT_PIXEL_CONVERSION_FACTOR = 32;

    /**
     * 图片宽度，单位像素
     */
    private final int imageWidth;

    /**
     * 像素转换因子
     */
    private final int pixelConversionFactor;

    public MultiImageCellWriteHandler() {
        this.imageWidth = DEFAULT_IMAGE_WIDTH;
        this.pixelConversionFactor = DEFAULT_PIXEL_CONVERSION_FACTOR;
    }

    public MultiImageCellWriteHandler(int imageWidth, int pixelConversionFactor) {
        this.imageWidth = imageWidth;
        this.pixelConversionFactor = pixelConversionFactor;
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (isHead || CollectionUtils.isEmpty(cellDataList)) {
            return;
        }

        WriteCellData<?> writeCellData = cellDataList.get(0);
        if (!writeCellData.getType().equals(CellDataTypeEnum.EMPTY) || StringUtils.isBlank(writeCellData.getStringValue())) {
            return;
        }

        String[] imageUrls = writeCellData.getStringValue().split(Constants.COMMA_SEPARATOR);

        // 设置最大单元格宽度，单位为像素
        if (imageUrls.length > MAX_IMAGE_SIZE.get()) {
            MAX_IMAGE_SIZE.set(imageUrls.length);

            int widthValue =  imageWidth * pixelConversionFactor;
            cell.getSheet().setColumnWidth(cell.getColumnIndex(), widthValue * MAX_IMAGE_SIZE.get() + pixelConversionFactor);
        }

        // 插入图片
        for (int i = 0; i < imageUrls.length; i++) {
            try {
                URL urlObj = new URL(imageUrls[i]);
                this.insertImage(cell.getSheet(), cell, IOUtils.toByteArray(urlObj.openStream()), i);
            } catch (MalformedURLException e) {
                log.error("图片地址url={}，转换异常", imageUrls[i], e);
            } catch (IOException e) {
                log.error("图片转换IO异常", e);
            }
        }
    }

    /**
     * 重新插入一个图片
     *
     * @param sheet       Excel页面
     * @param cell        表格元素
     * @param imageData   图片数据
     * @param i           图片顺序
     */
    public void insertImage(Sheet sheet, Cell cell, byte[] imageData, int i) {
        int picWidth = Units.pixelToEMU(imageWidth);
        int index = sheet.getWorkbook().addPicture(imageData, Workbook.PICTURE_TYPE_PNG);

        CreationHelper helper = sheet.getWorkbook().getCreationHelper();
        ClientAnchor anchor = helper.createClientAnchor();

        // 设置图片坐标，为了不让图片遮挡单元格的上边框和右边框，故 x1、x2、y1 这几个坐标点均向后移动了一个像素点
        anchor.setDx1(Units.pixelToEMU(1) + picWidth * i);
        anchor.setDx2(Units.pixelToEMU(1) + picWidth * (i + 1));
        anchor.setDy1(Units.pixelToEMU(1));
        anchor.setDy2(0);

        // 设置图片位置
        anchor.setCol1(cell.getColumnIndex());
        anchor.setCol2(cell.getColumnIndex());
        anchor.setRow1(cell.getRowIndex());
        anchor.setRow2(cell.getRowIndex() + 1);
        anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_DO_RESIZE);

        Drawing<?> drawing = sheet.getDrawingPatriarch();
        if (drawing == null) {
            drawing = sheet.createDrawingPatriarch();
        }
        drawing.createPicture(anchor, index);
    }
}
